Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: adjust precomputed assignments export for node environment #190

Conversation

sameerank
Copy link
Contributor

@sameerank sameerank commented Jan 9, 2025


labels: mergeable

Fixes: #issue

Motivation and Context

Description

A method for exporting precomputed assignments was added to the common sdk #160 and published in version 4.7.1

The end-user would use the function in the node SDK and so I checked that it works in the node environment. I found a couple things to improve:

  • crypto needs to be imported in node, the common sdk assumes it is a globally scoped variable which is only true in the browser environment
  • the common sdk is hard coded to assume that precomputed assignments in the configuration wire are obfuscated, so that should be the default format

How has this been tested?

Locally with yarn link and running the test I created in Eppo-exp/node-server-sdk#89

@@ -871,7 +871,7 @@ export default class EppoClient {
getPrecomputedAssignments(
subjectKey: string,
subjectAttributes: Attributes | ContextAttributes = {},
obfuscated = false,
obfuscated = true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hard coded to be true in other places in the common sdk, e.g.

So at the very least, the default here should be true if we let it support both formats

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#180 will drop support for this param.

Comment on lines 8 to 22
let getRandomValues: (length: number) => Uint8Array;
if (typeof window !== 'undefined' && window.crypto) {
// Browser environment
getRandomValues = (length: number) => window.crypto.getRandomValues(new Uint8Array(length));
} else {
// Node.js environment
import('crypto')
.then((crypto) => {
getRandomValues = (length: number) => new Uint8Array(crypto.randomBytes(length));
return;
})
.catch((error) => {
logger.error('Failed to load crypto module:', error);
});
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crypto isn't a global variable in the node environment and needs to be imported. Additional work will need to be done here to also make this work in react native.

Is there a better way to do this? Open to suggestions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for mentioning react native. could you please add support now as i'll need to dogfood it. chatgpt suggests:

let getRandomValues: (length: number) => Uint8Array;

if (typeof window !== 'undefined' && window.crypto?.getRandomValues) {
  // Browser environment
  getRandomValues = (length: number) => window.crypto.getRandomValues(new Uint8Array(length));
} else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
  // React Native environment (using react-native-get-random-values)
  import('react-native-get-random-values').then(() => {
    getRandomValues = (length: number) => {
      const array = new Uint8Array(length);
      return window.crypto.getRandomValues(array);
    };
  });
} else {
  // Node.js environment
  import('crypto')
    .then((crypto) => {
      getRandomValues = (length: number) => new Uint8Array(crypto.randomBytes(length));
    })
    .catch((error) => {
      console.error('Failed to load crypto module:', error);
      throw new Error('Crypto module is required in Node.js');
    });
}

// Export function for use in the library
export { getRandomValues };

the eppo react native sdk will add react-native-get-random-values as a dependency

Comment on lines +132 to +133
setSaltOverrideForTests,
decodePrecomputedFlag,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used in a test here and here

To verify that an initialized node client exports correctly obfuscated precomputed flags

@@ -19,6 +19,9 @@ module.exports = {
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
fallback: {
crypto: false, // Exclude crypto module in the browser bundle
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice find

Comment on lines 8 to 22
let getRandomValues: (length: number) => Uint8Array;
if (typeof window !== 'undefined' && window.crypto) {
// Browser environment
getRandomValues = (length: number) => window.crypto.getRandomValues(new Uint8Array(length));
} else {
// Node.js environment
import('crypto')
.then((crypto) => {
getRandomValues = (length: number) => new Uint8Array(crypto.randomBytes(length));
return;
})
.catch((error) => {
logger.error('Failed to load crypto module:', error);
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for mentioning react native. could you please add support now as i'll need to dogfood it. chatgpt suggests:

let getRandomValues: (length: number) => Uint8Array;

if (typeof window !== 'undefined' && window.crypto?.getRandomValues) {
  // Browser environment
  getRandomValues = (length: number) => window.crypto.getRandomValues(new Uint8Array(length));
} else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
  // React Native environment (using react-native-get-random-values)
  import('react-native-get-random-values').then(() => {
    getRandomValues = (length: number) => {
      const array = new Uint8Array(length);
      return window.crypto.getRandomValues(array);
    };
  });
} else {
  // Node.js environment
  import('crypto')
    .then((crypto) => {
      getRandomValues = (length: number) => new Uint8Array(crypto.randomBytes(length));
    })
    .catch((error) => {
      console.error('Failed to load crypto module:', error);
      throw new Error('Crypto module is required in Node.js');
    });
}

// Export function for use in the library
export { getRandomValues };

the eppo react native sdk will add react-native-get-random-values as a dependency

@sameerank sameerank merged commit 5dc25f4 into main Jan 9, 2025
8 checks passed
@sameerank sameerank deleted the sameeran/ff-3785-export-precomputed-configuration-wire-in-node-sdk branch January 9, 2025 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants